package controller

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"gitlab.local/DO-module/new-filemanage-module/src/core/directory"
	"gitlab.local/DO-module/new-filemanage-module/src/core/httplogger"
	"gitlab.local/DO-module/new-filemanage-module/src/core/middleware"
	"gitlab.local/DO-module/new-filemanage-module/src/service/folder"
	acl2 "gitlab.local/TerraMaster/tos-modules/core/acl"
	"gitlab.local/TerraMaster/tos-modules/database/sqlitemodel"
	directory2 "gitlab.local/TerraMaster/tos-modules/directory"
	//"gitlab.local/TerraMaster/tos-modules/middleware"
	//middleware2 "gitlab.local/DO-module/new-filemanage-module/src/core/middleware"
	"gitlab.local/DO-module/new-filemanage-module/src/core/middleware/xcsrf"
	//"gitlab.local/TerraMaster/tos-modules/middleware/xcsrf"
	"gitlab.local/TerraMaster/tos-modules/service/sharefolder"
	"gitlab.local/golibrary/openssl"
	"gitlab.local/golibrary/resp"
	"gitlab.local/golibrary/utils"
	"net/http"
	"os"
	"os/user"
	"path/filepath"
	"strconv"
	"strings"
)

type ShareFolder struct {
	folderService sharefolder.Service
	logger        httplogger.Logger
	folders       folder.FoldersService
}

func (s *ShareFolder) Router(httpService httplogger.Logger, engine *gin.Engine, checker middleware.AuthChecker, folderService sharefolder.Service, folder folder.FoldersService) {
	s.folderService = folderService
	s.logger = httpService
	s.folders = folder

	engine.GET("/folder/DownloadSecretKey", checker.LoginAuthed(), s.HandleDownloadSecretKey) //下载秘钥文件

	fold := engine.Group("/folder", xcsrf.XCSRF("header"), checker.LoginAuthed())
	{
		//获取目录列表
		fold.GET("/list", resp.WrapResp(s.HandleFolderList))
		//获取ISO列表
		fold.GET("/iso", resp.WrapResp(s.HandleImageList))
		//获取iso文件列表
		fold.GET("/iso/scan", resp.WrapResp(s.HandleScanIsoFiles))
		//创建iso文件夹
		fold.POST("/iso/create", resp.WrapResp(s.HandleIsoCreate))
		//删除iso文件夹
		fold.DELETE("/iso/:id", checker.CheckUserPasswd(), resp.WrapResp(s.HandleIsoDelete))
		//创建目录
		fold.POST("/create", resp.WrapResp(s.HandleFolderCreate))
		//根据id获取目录信息
		fold.GET("/res/:id", resp.WrapResp(s.HandleFolderInfo))
		//清空回收站
		fold.DELETE("/clearRecycle", resp.WrapResp(s.HandleClearRecycle))
		//修改目录设置
		fold.PUT("/res/:id", resp.WrapResp(s.HandleFolderEdit))
		//修改目录设置
		fold.PUT("/res/permission/:id", resp.WrapResp(s.HandleFolderEditPermission))
		//修改自定义权限
		fold.PUT("/res/acl", resp.WrapResp(s.HandleFolderRichAclEdit))
		//获取自定义权限
		fold.GET("/res/acl", resp.WrapResp(s.HandleFolderRichAclInfo))
		//获取可设置自定义权限的用户列表
		fold.GET("/res/acl/user", resp.WrapResp(s.HandleFolderRichAclUserList))
		//使继承权限显示化
		fold.POST("/res/acl/InheritedPermissionsCopy", resp.WrapResp(s.HandleInheritedPermissionsCopy))
		//排除继承权限
		fold.POST("/res/acl/InheritedPermissionsRemove", resp.WrapResp(s.HandleInheritedPermissionsRemove))
		//包含继承权限
		fold.POST("/res/acl/InheritedPermissionsAllow", resp.WrapResp(s.HandleInheritedPermissionsAllow))
		//检查目录名是否存在
		fold.GET("/check/:name", resp.WrapResp(s.HandleFolderExists))
		//删除目录
		fold.DELETE("/res/:id", checker.CheckUserPasswd(), resp.WrapResp(s.HandleFolderRemove))
		fold.PUT("/change", resp.WrapResp(s.HandleFolderChange))
		fold.POST("/ObtainSecretKey", resp.WrapResp(s.HandleExportSecretKey)) //获取秘钥文件路径
		fold.POST("/EcryptfsMount", resp.WrapResp(s.HandleEcryptfsMount))     //加密文件夹挂载
		fold.POST("/EcryptfsUmount", resp.WrapResp(s.HandleEcryptfsUmount))   //加密文件夹卸载
		//nfs
		fold.POST("/SetNFSAcl", resp.WrapResp(s.HandleSetNFSAcl))        //设置nfs配置
		fold.GET("/GetNFSAclList", resp.WrapResp(s.HandleGetNFSAclList)) //获取NFSAcl列表
		fold.DELETE("/DelNFSAcl", resp.WrapResp(s.HandleDelNFSAcl))      //删除NFSAcl
		fold.POST("/UpdateNFSAcl", resp.WrapResp(s.HandleUpdateNFSAcl))  //更新NFSAcl配置
		//smb
		fold.POST("/SetSmbAcl", resp.WrapResp(s.HandleSetSmbAcl))        //设置SmbAcl配置
		fold.GET("/GetSmbAclList", resp.WrapResp(s.HandleGetSmbAclList)) //获取SmbAcl配置列表
		fold.DELETE("/DelSmbAcl", resp.WrapResp(s.HandleDelSmbAcl))      //删除SmbAcl配置
		fold.POST("/UpdateSmbAcl", resp.WrapResp(s.HandleUpdateSmbAcl))  //更新SmbAcl配置
		//webdav
		fold.POST("/SetWebDavAcl", resp.WrapResp(s.HandleSetWebdavAcl))        //设置WebDav配置
		fold.GET("/GetWebDavAclList", resp.WrapResp(s.HandleGetWebdavAclList)) //获取WebDav配置列表
		fold.DELETE("/DelWebDavAcl", resp.WrapResp(s.HandleDelWebdavAcl))      //删除WebDav配置
		fold.POST("/UpdateWebDavAcl", resp.WrapResp(s.HandleUpdateWebdavAcl))  //更新WebDav配置

		fold.GET("/SnapshotOccupationFolder", resp.WrapResp(s.HandleSnapshotOccupationFolder)) //快照占用文件夹
		fold.POST("/MvShareFolder", resp.WrapResp(s.HandleMvShareFolder))                      //移动共享文件夹
		fold.GET("/MvShareFolderPlan", resp.WrapResp(s.HandleMvShareFolderPlan))               //获取移动共享文件夹进度

	}
	foldAPP := engine.Group("/folder_app")
	{
		foldAPP.GET("/getShareFolderListByVolume/:volume_path", resp.WrapResp(s.HandleShareFolderListByVolume)) //根据卷地址获取卷下的所有共享文件夹绝对路径

	}
}

// HandleFolderList 加密文件夹列表
func (s *ShareFolder) HandleFolderList(c *gin.Context) (interface{}, error) {
	username, err := middleware.GetUserName(c)
	if err != nil {
		return nil, err
	}
	return s.folderService.GetFolderList(username), nil
}

func (s *ShareFolder) HandleImageList(*gin.Context) (interface{}, error) {
	return s.folderService.GetIsoList(), nil
}

func (s *ShareFolder) HandleScanIsoFiles(*gin.Context) (interface{}, error) {
	return s.folderService.ScanIsoFiles(), nil
}

func (s *ShareFolder) HandleIsoCreate(c *gin.Context) (interface{}, error) {
	option := sqlitemodel.Share{}
	if e := c.ShouldBind(&option); e != nil {
		return false, e
	}
	e := s.folderService.CreateIsoFolder(option)
	if e == nil {
		s.logger.Infoln(c, fmt.Sprintf(httplogger.AddIosFolder, option.FolderName))
	}
	return e == nil, e
}

func (s *ShareFolder) HandleIsoDelete(c *gin.Context) (interface{}, error) {
	id, e := strconv.Atoi(c.Param("id"))
	if e != nil || id == 0 {
		return false, errors.New("invalid folder id")
	}
	share := s.folderService.GetIsoList()
	e = s.folderService.DeleteIsoFolder(id)
	if e == nil {
		for i := range share {
			if share[i].FolderId == id {
				s.logger.Infoln(c, fmt.Sprintf(httplogger.DelIosFolder, share[i].FolderName))
				break
			}
		}
	}
	return e == nil, e
}

// HandleEcryptfsMount 加密文件夹挂载
func (s *ShareFolder) HandleEcryptfsMount(c *gin.Context) (interface{}, error) {
	path := c.PostForm("path")
	pwd := c.PostForm("pwd")
	file, _ := c.FormFile("file")
	if path == "" {
		return false, errors.New("parameter incomplete")
	}
	if (pwd == "" && file == nil) || (pwd != "" && file != nil) {
		return false, errors.New("choose one of the password and secret key files")
	}

	if pwd != "" {
		pwd, _ = openssl.JsEcryptDecode(pwd)
		//var password []rune
		//for _, v := range pwd {
		//	if unicode.IsPunct(v) || unicode.IsSymbol(v) || unicode.Is(unicode.Han, v) {
		//		password = append(password, '\\')
		//	}
		//	password = append(password, v)
		//}
		//pwd = string(password)
	}

	if file != nil {
		pwd = fmt.Sprintf(directory.PassphrasePath, filepath.Base(path))
		if e := os.MkdirAll(filepath.Dir(pwd), 0744); e != nil {
			return false, e
		}
		if e := c.SaveUploadedFile(file, pwd); e != nil {
			return false, e
		}
	}
	return s.folderService.EcryptfsMount(path, pwd)
}

// HandleEcryptfsUmount 加密文件夹卸载
func (s *ShareFolder) HandleEcryptfsUmount(c *gin.Context) (interface{}, error) {
	path := c.PostForm("path")
	if path == "" {
		return "", errors.New("parameter Incomplete")
	}
	return s.folderService.EcryptfsUmount(path)
}

// HandleExportSecretKey 获取秘钥文件路径
func (s *ShareFolder) HandleExportSecretKey(c *gin.Context) (interface{}, error) {
	path := c.PostForm("path")
	pwd := c.PostForm("pwd")
	if path == "" || pwd == "" {
		return "", errors.New("parameter Incomplete")
	}
	return s.folderService.ObtainSecretKey(path, pwd)
}

// HandleDownloadSecretKey 下载秘钥文件
func (s *ShareFolder) HandleDownloadSecretKey(c *gin.Context) {
	data := c.Query("data")
	if data == "" {
		c.String(http.StatusInternalServerError, "parameter Incomplete")
		return
	}
	src := utils.Base64Decode(data)
	if filepath.Dir(directory.PassphrasePath) != filepath.Dir(src) { //限制下载文件目录
		c.String(http.StatusInternalServerError, "error downloading file path")
		return
	}
	_ = utils.DownloadFile(c, []string{src}, "")
}

func (s *ShareFolder) HandleFolderCreate(c *gin.Context) (interface{}, error) {
	var param directory2.CreateFolder
	if e := c.ShouldBind(&param); e != nil {
		return false, e
	}
	username, err := middleware.GetUserName(c)
	if err != nil {
		return nil, err
	}
	err = s.folderService.CreateFolder(username, &param)
	if err == nil {
		s.logger.Infoln(c, fmt.Sprintf(httplogger.AddFolder, param.FolderName))
	}
	return err == nil, err
}

func (s *ShareFolder) HandleFolderExists(c *gin.Context) (interface{}, error) {
	name := c.Param("name")
	if name == "" {
		return nil, errors.New("param error")
	}
	return s.folderService.IsExistsFolderCaseInsensitive(name), nil
}

func (s *ShareFolder) HandleFolderInfo(c *gin.Context) (interface{}, error) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil || id == 0 {
		return nil, errors.New("param id error")
	}
	return s.folderService.GetFolderInfo(id)
}

func (s *ShareFolder) HandleClearRecycle(c *gin.Context) (interface{}, error) {
	name := c.Query("name")
	if name == "" {
		return false, errors.New("param error")
	}
	path := filepath.Join(name, "#recycle")
	_, _ = utils.ShellExec(fmt.Sprintf("rm -rf %s/* %s/.*", path, path))
	return true, nil
}

func (s *ShareFolder) HandleFolderEdit(c *gin.Context) (interface{}, error) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil || id == 0 {
		return false, errors.New("param id error")
	}
	var param sharefolder.Detail
	if err = c.ShouldBind(&param); err != nil {
		return false, err
	}
	return err == nil, s.folderService.EditFolder(id, param)
}

func (s *ShareFolder) HandleFolderEditPermission(c *gin.Context) (interface{}, error) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil || id == 0 {
		return false, errors.New("param id error")
	}
	var param sharefolder.Detail
	if err = c.ShouldBind(&param); err != nil {
		return false, err
	}
	return err == nil, s.folderService.EditFolderPermission(id, param)
}

func (s *ShareFolder) HandleFolderRichAclEdit(c *gin.Context) (interface{}, error) {
	path := c.Query("path")
	if path == "" {
		return nil, errors.New("request path error")
	}

	var param acl2.FolderAttrs
	if err := c.ShouldBind(&param); err != nil {
		return false, err
	}
	return nil, s.folderService.EditFolderRichAcl(path, param)
}

func (s *ShareFolder) HandleFolderRichAclInfo(c *gin.Context) (interface{}, error) {
	path := c.Query("path")
	if path == "" {
		return nil, errors.New("request path error")
	}

	return s.folderService.GetFolderRichAclInfo(path)
}

func (s *ShareFolder) HandleFolderRichAclUserList(c *gin.Context) (interface{}, error) {
	path := c.Query("path")
	from := c.Query("type")
	if path == "" {
		return nil, errors.New("request path error")
	}

	path = path + "&" + from
	return s.folderService.GetRichAclUserList(path), nil
}

func (s *ShareFolder) HandleInheritedPermissionsCopy(c *gin.Context) (interface{}, error) {
	path := c.Query("path")
	if path == "" {
		return nil, errors.New("request path error")
	}

	return nil, s.folderService.Acl().InheritedPermissionsCopy(path)
}

func (s *ShareFolder) HandleInheritedPermissionsRemove(c *gin.Context) (interface{}, error) {
	path := c.Query("path")
	if path == "" {
		return nil, errors.New("request path error")
	}

	return nil, s.folderService.Acl().InheritedPermissionsRemove(path)
}

func (s *ShareFolder) HandleInheritedPermissionsAllow(c *gin.Context) (interface{}, error) {
	path := c.Query("path")
	if path == "" {
		return nil, errors.New("request path error")
	}

	return nil, s.folderService.Acl().InheritedPermissionsAllow(path)
}

func (s *ShareFolder) HandleFolderRemove(c *gin.Context) (interface{}, error) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil || id == 0 {
		return false, errors.New("parameter error")
	}
	Detail, err1 := s.folderService.GetFolderInfo(id)
	output, err := utils.ShellExec(fmt.Sprintf("ls -l /%s/\\@snapshot/%s/ | grep GMT+08 | wc -l", Detail.Device, Detail.FolderName))
	if err != nil {
		return false, errors.New("Command error")
	}
	result := strings.ReplaceAll(output, "\n", "")
	num, _ := strconv.Atoi(result)
	if num > 0 {
		return false, errors.New("A snapshot exists in the shared folder")
	}

	err = s.folderService.DeleteFolder(id)
	if err == nil && err1 == nil {
		s.logger.Infoln(c, fmt.Sprintf(httplogger.DelFolder, Detail.FolderName))
	}
	return err == nil, err
}

func (s *ShareFolder) HandleFolderChange(c *gin.Context) (interface{}, error) {
	mntPath := c.PostForm("mount_point")
	if mntPath == "" {
		return "", errors.New("param error")
	}
	return "", s.folderService.ChangeVolume(mntPath)
}

// HandleSetNFSAcl 设置nfs配置
func (s *ShareFolder) HandleSetNFSAcl(c *gin.Context) (interface{}, error) {
	var data sharefolder.NFSAcl
	if err := c.BindJSON(&data); err != nil {
		return false, err
	}
	err := s.folderService.SetNFSAcl(data)
	return err == nil, err
}

// HandleGetNFSAclList 获取NFSAcl列表
func (s *ShareFolder) HandleGetNFSAclList(c *gin.Context) (interface{}, error) {
	str := c.Query("folder_id")
	folderId, err := strconv.Atoi(str)
	if err != nil {
		return nil, err
	}
	return s.folderService.GetNFSAclList(folderId)
}

// HandleDelNFSAcl 删除NFSAcl
func (s *ShareFolder) HandleDelNFSAcl(c *gin.Context) (interface{}, error) {
	str := c.Query("hash")
	if str == "" {
		return false, errors.New("hash is empty")
	}
	err := s.folderService.DelNFSAcl(str)
	return err == nil, err
}

// HandleUpdateNFSAcl 更新NFSAcl配置
func (s *ShareFolder) HandleUpdateNFSAcl(c *gin.Context) (interface{}, error) {
	var data sharefolder.NFSAcl
	if err := c.BindJSON(&data); err != nil {
		return false, err
	}
	err := s.folderService.UpdateNFSAcl(data)
	return err == nil, err
}

// HandleGetSmbAclList 获取SmbAcl配置列表
func (s *ShareFolder) HandleGetSmbAclList(c *gin.Context) (interface{}, error) {
	atoi, _ := strconv.Atoi(c.Query("folder_id"))
	if atoi <= 0 {
		return nil, errors.New("folder_id error")
	}
	return s.folderService.GetSmbAclList(atoi)
}

func (s *ShareFolder) HandleGetWebdavAclList(c *gin.Context) (interface{}, error) {
	atoi, _ := strconv.Atoi(c.Query("folder_id"))
	if atoi <= 0 {
		return nil, errors.New("folder_id error")
	}
	return s.folderService.GetWebdavAclList(atoi)
}

// HandleUpdateSmbAcl 更新SmbAcl配置
func (s *ShareFolder) HandleUpdateSmbAcl(c *gin.Context) (interface{}, error) {
	var data sharefolder.SmbAcl
	if err := c.BindJSON(&data); err != nil {
		return nil, err
	}
	err := s.folderService.UpdateSmbAcl(data)
	return err == nil, err
}

// HandleUpdateWebdavAcl 更新SmbAcl配置
func (s *ShareFolder) HandleUpdateWebdavAcl(c *gin.Context) (interface{}, error) {
	var data sharefolder.SmbAcl
	if err := c.BindJSON(&data); err != nil {
		return nil, err
	}
	err := s.folderService.UpdateWebdavAcl(data)
	return err == nil, err
}

// HandleDelSmbAcl 删除SmbAcl配置
func (s *ShareFolder) HandleDelSmbAcl(c *gin.Context) (interface{}, error) {
	hash := c.Query("hash")
	if hash == "" {
		return nil, errors.New("hash is empty")
	}
	err := s.folderService.DelSmbAcl(hash)
	return err == nil, err
}

// HandleDelWebdavAcl 删除SmbAcl配置
func (s *ShareFolder) HandleDelWebdavAcl(c *gin.Context) (interface{}, error) {
	hash := c.Query("hash")
	if hash == "" {
		return nil, errors.New("hash is empty")
	}
	err := s.folderService.DelWebdavAcl(hash)
	return err == nil, err
}

// HandleSetSmbAcl 设置SmbAcl配置
func (s *ShareFolder) HandleSetSmbAcl(c *gin.Context) (interface{}, error) {
	var data sharefolder.SmbAcl
	if err := c.BindJSON(&data); err != nil {
		return nil, err
	}
	err := s.folderService.SetSmbAcl(data)
	return err == nil, err
}

func (s *ShareFolder) HandleSetWebdavAcl(c *gin.Context) (interface{}, error) {
	var data sharefolder.SmbAcl
	if err := c.BindJSON(&data); err != nil {
		return nil, err
	}
	err := s.folderService.SetWebDavAcl(data)
	return err == nil, err
}

func (s *ShareFolder) HandleSetWebDavAcl(c *gin.Context) (interface{}, error) {
	var data sharefolder.SmbAcl
	if err := c.BindJSON(&data); err != nil {
		return nil, err
	}
	err := s.folderService.SetSmbAcl(data)
	return err == nil, err
}

// HandleSnapshotOccupationFolder 快照占用文件夹
func (s *ShareFolder) HandleSnapshotOccupationFolder(*gin.Context) (interface{}, error) {
	return s.folderService.SnapshotOccupationFolder(), nil
}

// HandleMvShareFolder 移动共享文件夹
func (s *ShareFolder) HandleMvShareFolder(c *gin.Context) (interface{}, error) {
	var data struct {
		Path   string `json:"path"`
		Volume string `json:"volume"`
	}
	if err := c.BindJSON(&data); err != nil {
		return 0, err
	}

	username, err := middleware.GetUserName(c)
	if err != nil {
		return nil, err
	}
	return s.folderService.MvShareFolder(data.Path, data.Volume, username, c.Request.Context())
}

// HandleMvShareFolderPlan 获取移动共享文件夹进度
func (s *ShareFolder) HandleMvShareFolderPlan(*gin.Context) (interface{}, error) {
	return s.folderService.MvShareFolderPlan()
}

// HandleShareFolderListByVolume
// @Description: 根据一个卷目录，获取到目录下的共享文件绝对路径
// @receiver s
// @param c
// @return interface{}
// @return error
func (s *ShareFolder) HandleShareFolderListByVolume(c *gin.Context) (interface{}, error) {
	param := c.Param("volume_path")
	if param == "" {
		return false, errors.New("invalid folder volumePath")
	}

	current, err := user.Current()
	if err != nil {
		return false, errors.New("user query failed")
	}
	strList := make([]string, 0)
	filter, err := s.folders.GetHomeListFilter(current.Username)
	if err != nil {
		return nil, err
	}
	//过滤权限
	for _, f := range filter {
		if f.Volume == param && f.Name != "homes" && f.Name != current.Username {
			strList = append(strList, f.Path)
		}
	}
	return strList, nil
}
